package com.thinkgsp.jxc.service.impl;

import java.math.BigDecimal;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.thinkgsp.jxc.model.Dept;
import com.thinkgsp.jxc.model.RpAPayBill;
import com.thinkgsp.jxc.model.RpARecBill;
import com.thinkgsp.jxc.model.RpArpBill;
import com.thinkgsp.jxc.model.RpBill;
import com.thinkgsp.jxc.model.RpBillDetail;
import com.thinkgsp.jxc.model.RpContact;
import com.thinkgsp.jxc.model.RpContactBalance;
import com.thinkgsp.jxc.model.RpOtherAPayBill;
import com.thinkgsp.jxc.model.RpOtherARecBill;
import com.thinkgsp.jxc.model.RpPayBill;
import com.thinkgsp.jxc.model.RpRecBill;
import com.thinkgsp.jxc.persistence.BillMapper;
import com.thinkgsp.jxc.persistence.ContactBalanceMapper;
import com.thinkgsp.jxc.persistence.RpArpBillMapper;
import com.thinkgsp.jxc.persistence.RpBillMapper;
import com.thinkgsp.jxc.persistence.RpContactMapper;
import com.thinkgsp.jxc.service.RpService;
import com.thinkgsp.jxc.service.ServiceException;
import com.thinkgsp.sys.model.SysAccountPeriod;

/**
 * 应收应付模块业务基类
 * @author evan
 *
 */
@Transactional
public class RpServiceImpl extends GeneralServiceImpl implements RpService {
	
	@Autowired
	protected RpBillMapper rpBillMapper;
	@Autowired
	protected RpArpBillMapper arpBillMapper;
	@Autowired
	protected RpContactMapper contactMapper;
	@Autowired
	protected ContactBalanceMapper cbMapper;
	@Autowired
	protected BillMapper billMapper;
	
	public void setRpArpBillMapper(RpArpBillMapper arpBillMapper) {
		this.arpBillMapper = arpBillMapper;
	}

	public void setRpContactMapper(RpContactMapper contactMapper) {
		this.contactMapper = contactMapper;
	}

	public void setContactBalanceMapper(ContactBalanceMapper cbMapper) {
		this.cbMapper = cbMapper;
	}
	
	public void setBillMapper(BillMapper billMapper) {
		this.billMapper = billMapper;
	}
	
	public void setRpBillMapper(RpBillMapper rpBillMapper) {
		this.rpBillMapper = rpBillMapper;
	}
	
	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.RpBillService#saveRecBill(com.thinkgsp.jxc.model.RpRecBill)
	 */
	public void saveRecBill(RpRecBill bill) throws ServiceException {
		if(!checkBillAmount(bill)) {
			throw new ServiceException("单据结算金额与明细结算金额合计不符。");
		}
		SysAccountPeriod currPeriod = periodMapper.getCurrentPeriod();
		if(!currPeriod.getFyear().equals(bill.getFyear()) ||
				!currPeriod.getPeriod().equals(bill.getPeriod())) {
			
			log.debug("RecBill:" + bill.getRpBillId() + " year:" + bill.getFyear() + ";period:" + bill.getPeriod());
			throw new ServiceException("不是当期单据,不允许修改。");
		}
		if(bill.getRpBillId() == null || bill.getRpBillId() == 0L) {
			rpBillMapper.insertRpBill(bill);
			for(RpBillDetail detail : bill.getDetails()) {
				detail.setRpBillId(bill.getRpBillId());
				rpBillMapper.insertRpBillDetail(detail);
			}
		} else {
			RpRecBill newBill = rpBillMapper.getRpBill(bill.getRpBillId());
			if(newBill.getArchived()) {
				throw new ServiceException("本单据已经归档，不允许修改。");
			} 
			rpBillMapper.updateRpBill(bill);
			if(bill.getDetails() == null || bill.getDetails().size()==0) {
				rpBillMapper.deleteRpBillDetail(bill.getRpBillId());
			} else {
				rpBillMapper.deleteRpBillDetailNotIn(bill.getRpBillId(), bill.getDetails());
			}
			for(RpBillDetail detail : bill.getDetails()) {
				if(detail.getId() == null || detail.getId() == 0L) {
					detail.setRpBillId(bill.getRpBillId());
					rpBillMapper.insertRpBillDetail(detail);
				} else {
					rpBillMapper.updateRpBillDetail(detail);
				}
			}
		}
		
		if(configuration.isRpBillSaveAndArchived()) {
			archiveRecBill(bill.getRpBillId());
			bill.setArchived(true);
		}
	}
	
	

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.RpBillService#savePayBill(com.thinkgsp.jxc.model.RpPayBill)
	 */
	public void savePayBill(RpPayBill bill) throws ServiceException {
		if(!checkBillAmount(bill)) {
			throw new ServiceException("单据结算金额与明细结算金额合计不符。");
		}
		SysAccountPeriod currPeriod = periodMapper.getCurrentPeriod();
		if(!currPeriod.getFyear().equals(bill.getFyear()) ||
				!currPeriod.getPeriod().equals(bill.getPeriod())) {
			
			log.debug("RecBill:" + bill.getRpBillId() + " year:" + bill.getFyear() + ";period:" + bill.getPeriod());
			throw new ServiceException("不是当期单据，不允许修改。");
		}
		if(bill.getRpBillId() == null || bill.getRpBillId() == 0L) {
			rpBillMapper.insertRpBill(bill);
			for(RpBillDetail detail : bill.getDetails()) {
				detail.setRpBillId(bill.getRpBillId());
				rpBillMapper.insertRpBillDetail(detail);
			}
		} else {
			RpPayBill newBill = rpBillMapper.getRpBill(bill.getRpBillId());
			if(newBill.getArchived()) {
				throw new ServiceException("本单据已经归档，不允许修改。");
			} 
			rpBillMapper.updateRpBill(bill);
			if(bill.getDetails() == null || bill.getDetails().size()==0) {
				rpBillMapper.deleteRpBillDetail(bill.getRpBillId());
			} else {
				rpBillMapper.deleteRpBillDetailNotIn(bill.getRpBillId(), bill.getDetails());
			}
			for(RpBillDetail detail : bill.getDetails()) {
				if(detail.getId() == null || detail.getId() == 0L) {
					detail.setRpBillId(bill.getRpBillId());
					rpBillMapper.insertRpBillDetail(detail);
				} else {
					rpBillMapper.updateRpBillDetail(detail);
				}
			}
		}
		if(configuration.isRpBillSaveAndArchived()) {
			archivePayBill(bill.getRpBillId());
			bill.setArchived(true);
		}
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.RpBillService#deleteRecBill(java.lang.Long)
	 */
	public void deleteRecBill(Long billId) throws ServiceException {
		RpRecBill bill = rpBillMapper.getRpBill(billId);
		if(bill.getArchived()) {
			throw new ServiceException("单据已经归档，不允许删除。");
		}
		rpBillMapper.deleteRpBillDetail(billId);
		int cnt = rpBillMapper.deleteRpBill(billId);
		if(cnt == 0) {
			throw new ServiceException("删除收款单失败，原因：删除记录数为零。");
		}
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.RpBillService#deletePayBill(java.lang.Long)
	 */
	public void deletePayBill(Long billId) throws ServiceException {
		RpPayBill bill = rpBillMapper.getRpBill(billId);
		if(bill.getArchived()) {
			throw new ServiceException("单据已经归档，不允许删除。");
		}
		rpBillMapper.deleteRpBillDetail(billId);
		int cnt = rpBillMapper.deleteRpBill(billId);
		if(cnt == 0) {
			throw new ServiceException("删除收款单失败，原因：删除记录数为零。");
		}
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.RpBillService#archiveRecBill(java.lang.Long)
	 */
	public void archiveRecBill(Long billId) throws ServiceException {
		RpRecBill recBill = rpBillMapper.getRpBill(billId);
		if(recBill.getArchived()) {
			throw new ServiceException("本单据已经被其他用户归档。");
		}
		SysAccountPeriod currPeriod = periodMapper.getCurrentPeriod();
		if(!currPeriod.getFyear().equals(recBill.getFyear()) ||
				!currPeriod.getPeriod().equals(recBill.getPeriod())) {
			
			log.debug("RecBill:" + recBill.getRpBillId() + " year:" + recBill.getFyear() + ";period:" + recBill.getPeriod());
			throw new ServiceException("不是当期单据，不允许归档。");
		}
		BigDecimal amount = recBill.getAmount().add(recBill.getDiscount());
		if(amount.compareTo(BigDecimal.ZERO) == 0) {
			throw new ServiceException("单据金额无效:" + amount.toString());
		}
		contactMapper.recordContactByRpBill(recBill);
		Integer year = recBill.getFyear();
		Integer period = recBill.getPeriod();
		Integer custId = recBill.getCustSuppId();
		Integer deptId = recBill.getDeptId();
		Integer empId = recBill.getEmpId();
		RpContactBalance balance = findContactBalance(1, year, period, custId, deptId, empId);
		if(balance == null) {
			balance = initContactBalance(1, year, period, custId, deptId, empId);
		}
		cbMapper.recordAccountsReceivableForCredit(balance.getId(), amount);
		rpBillMapper.billArchive(billId, true);
		
		
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.RpBillService#unArchiveRecBill(java.lang.Long)
	 */
	public void unArchiveRecBill(Long billId) throws ServiceException {
		RpRecBill recBill = rpBillMapper.getRpBill(billId);
		if(!recBill.getArchived()) {
			throw new ServiceException("本单据未归档，不允许反归档。");
		}
		SysAccountPeriod currPeriod = periodMapper.getCurrentPeriod();
		if(!currPeriod.getFyear().equals(recBill.getFyear()) ||
				!currPeriod.getPeriod().equals(recBill.getPeriod())) {
			throw new ServiceException("不是当期单据，不允许反归档。");
		}
		if(contactMapper.isRpBillCheck(billId)) {
			throw new ServiceException("本单据已经核销，不允许反归档。");
		}
		
		Integer year = recBill.getFyear();
		Integer period = recBill.getPeriod();
		Integer custId = recBill.getCustSuppId();
		Integer deptId = recBill.getDeptId();
		Integer empId = recBill.getEmpId();	
		RpContact contact = contactMapper.findRpContactByRpBill(recBill.getRpBillId());
		if(contact == null) {
			throw new ServiceException("反归档失败，未检索到往来记录。");
		}
		if(contact.getAmount().compareTo(contact.getRemAmount()) != 0) {
			throw new ServiceException("本单据已经核销，不允许反归档。");
		}
		int cnt = contactMapper.revokeContactByRpBill(billId);
		if(cnt == 0) {
			throw new ServiceException("删除往来记录失败，请检查单据是否已经核销。");
		}
		RpContactBalance balance = findContactBalance(1, year, period, custId, deptId, empId);
		if(balance == null) {
			throw new ServiceException("反归档失败，未检索到往来余额记录。");
		}
		cbMapper.recordAccountsReceivableForCredit(balance.getId(), recBill.getSettleAmount().negate());
		rpBillMapper.billArchive(recBill.getRpBillId(), false);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.RpBillService#archivePayBill(java.lang.Long)
	 */
	public void archivePayBill(Long billId) throws ServiceException {
		RpPayBill payBill = rpBillMapper.getRpBill(billId);
		if(payBill.getArchived()) {
			throw new ServiceException("本单据已经被其他用户归档。");
		}
		SysAccountPeriod currPeriod = periodMapper.getCurrentPeriod();
		if(!currPeriod.getFyear().equals(payBill.getFyear()) ||
				!currPeriod.getPeriod().equals(payBill.getPeriod())) {
			log.debug("APayBill:" + payBill.getRpBillId() + " year:" + payBill.getFyear() + ";period:" + payBill.getPeriod());
			throw new ServiceException("不是当期单据，不允许归档。");
		}
		BigDecimal amount = payBill.getAmount().add(payBill.getDiscount());
		if(amount.compareTo(BigDecimal.ZERO) == 0) {
			throw new ServiceException("单据金额无效:" + amount.toString());
		}	
		Integer year = payBill.getFyear();
		Integer period = payBill.getPeriod();
		Integer custId = payBill.getCustSuppId();
		Integer deptId = payBill.getDeptId();
		Integer empId = payBill.getEmpId();		
		contactMapper.recordContactByRpBill(payBill);
		RpContactBalance balance = findContactBalance(-1, year, period, custId, deptId, empId);
		if(balance == null) {
			balance = initContactBalance(-1, year, period, custId, deptId, empId);
		}
		cbMapper.recordAccountsPayableForDebit(balance.getId(), amount);
		rpBillMapper.billArchive(billId, true);
		
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.RpBillService#unArchivePaybill(java.lang.Long)
	 */
	public void unArchivePayBill(Long billId) throws ServiceException {
		RpPayBill payBill = rpBillMapper.getRpBill(billId);
		if(!payBill.getArchived()) {
			throw new ServiceException("本单据未归档，不允许反归档。");
		}
		SysAccountPeriod currPeriod = periodMapper.getCurrentPeriod();
		if(!currPeriod.getFyear().equals(payBill.getFyear()) ||
				!currPeriod.getPeriod().equals(payBill.getPeriod())) {
			throw new ServiceException("不是当期单据，不允许反归档。");
		}
		if(contactMapper.isRpBillCheck(billId)) {
			throw new ServiceException("本单据已经核销，不允许反归档。");
		}
		Integer year = payBill.getFyear();
		Integer period = payBill.getPeriod();
		Integer custId = payBill.getCustSuppId();
		Integer deptId = payBill.getDeptId();
		Integer empId = payBill.getEmpId();
		RpContact contact = contactMapper.findRpContactByRpBill(billId);
		if(contact == null) {
			throw new ServiceException("反归档失败，未检索到往来记录。");
		}
		if(contact.getAmount().compareTo(contact.getRemAmount()) != 0) {
			throw new ServiceException("本单据已经核销，不允许反归档。");
		}
		int cnt = contactMapper.revokeContactByRpBill(billId);
		if(cnt == 0) {
			throw new ServiceException("删除往来记录失败，请检查单据是否已经核销。");
		}		
		RpContactBalance balance = findContactBalance(-1, year, period, custId, deptId, empId);
		if(balance == null) {
			throw new ServiceException("反归档失败，未检索到往来余额记录。");
		}
		try {
			cbMapper.recordAccountsPayableForDebit(balance.getId(), payBill.getSettleAmount().negate());
			rpBillMapper.billArchive(billId, false);
		} catch(Exception e) {
			log.error(e);
			throw new ServiceException(e.getMessage());
		}
	}
	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.RpArpBillService#saveArpBill(com.thinkgsp.jxc.model.RpArpBill)
	 */
	public void saveArpBill(RpArpBill bill) throws ServiceException {
		if(bill.getArchived()) {
			throw new ServiceException("单据已经归档，不能修改。");
		}
		
		if(bill.getArpBillId() == null || bill.getArpBillId() == 0) {
			arpBillMapper.insertArpBill(bill);
		} else {
			RpArpBill arp = arpBillMapper.getArpBill(bill.getArpBillId());
			if(arp != null && arp.getArchived()) {
				throw new ServiceException("单据已经被其他用户归档，不能修改。");
			}
			arpBillMapper.updateArpBill(bill);
		}
		if(configuration.isRpBillSaveAndArchived()) {
			if(bill instanceof RpAPayBill) {
				archiveAPayBill(bill.getArpBillId());
			} else {
				archiveARecBill(bill.getArpBillId());
			}
			bill.setArchived(true);
		}
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.RpArpBillService#deleteArpBill(java.lang.Long)
	 */
	public void deleteArpBill(Long id) throws ServiceException {
		RpArpBill bill = arpBillMapper.getArpBill(id);
		if(bill.getArchived()) {
			throw new ServiceException("本单据已经归档，不能删除。");
		}
		int cnt = arpBillMapper.deleteArpBill(id);
		if(cnt == 0) {
			throw new ServiceException("删除失败。");
		}
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.RpArpBillService#archiveARecBill(java.lang.Long)
	 */
	public void archiveARecBill(Long billId) throws ServiceException {
		RpARecBill arecBill = arpBillMapper.getArpBill(billId);
		if(arecBill.getArchived()) {
			throw new ServiceException("本单据已经被其他用户归档。");
		}
		SysAccountPeriod currPeriod = periodMapper.getCurrentPeriod();
		if(!currPeriod.getFyear().equals(arecBill.getFyear()) ||
				!currPeriod.getPeriod().equals(arecBill.getPeriod())) {
			
			log.debug("ARecBill:" + arecBill.getArpBillId() + " year:" + arecBill.getFyear() + ";period:" + arecBill.getPeriod());
			throw new ServiceException("不是当期单据，不允许归档。");
		}
		BigDecimal amount = arecBill.getAmount();
		if(amount.compareTo(BigDecimal.ZERO) == 0) {
			throw new ServiceException("单据金额无效:" + amount.toString());
		}
		contactMapper.recordContactByArpBill(arecBill);
		Integer year = arecBill.getFyear();
		Integer period = arecBill.getPeriod();
		Integer custId = arecBill.getCustSuppId();
		Integer deptId = arecBill.getDeptId();
		Integer empId = arecBill.getEmpId();
		RpContactBalance balance = findContactBalance(1, year, period, custId, deptId, empId);
		if(balance == null) {
			balance = initContactBalance(1, year, period, custId, deptId, empId);
		}
		cbMapper.recordAccountsReceivableForDebit(balance.getId(), amount);
		arpBillMapper.billArchive(billId, true);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.RpArpBillService#archiveAPayBill(java.lang.Long)
	 */
	public void archiveAPayBill(Long billId) throws ServiceException {
		RpAPayBill apayBill = arpBillMapper.getArpBill(billId);
		if(apayBill.getArchived()) {
			throw new ServiceException("本单据已经被其他用户归档。");
		}
		SysAccountPeriod currPeriod = periodMapper.getCurrentPeriod();
		if(!currPeriod.getFyear().equals(apayBill.getFyear()) ||
				!currPeriod.getPeriod().equals(apayBill.getPeriod())) {
			log.debug("APayBill:" + apayBill.getArpBillId() + " year:" + apayBill.getFyear() + ";period:" + apayBill.getPeriod());
			throw new ServiceException("不是当期单据，不允许归档。");
		}
		BigDecimal amount = apayBill.getAmount();
		if(amount.compareTo(BigDecimal.ZERO) == 0) {
			throw new ServiceException("单据金额无效:" + amount.toString());
		}	
		Integer year = apayBill.getFyear();
		Integer period = apayBill.getPeriod();
		Integer custId = apayBill.getCustSuppId();
		Integer deptId = apayBill.getDeptId();
		Integer empId = apayBill.getEmpId();		
		contactMapper.recordContactByArpBill(apayBill);
		RpContactBalance balance = findContactBalance(-1, year, period, custId, deptId, empId);
		if(balance == null) {
			balance = initContactBalance(-1, year, period, custId, deptId, empId);
		}
		cbMapper.recordAccountsPayableForCredit(balance.getId(), amount);
		arpBillMapper.billArchive(billId, true);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.RpArpBillService#unArchiveARecBill(java.lang.Long)
	 */
	public void unArchiveARecBill(Long billId) throws ServiceException {
		RpARecBill arecBill = arpBillMapper.getArpBill(billId);
		if(!arecBill.getArchived()) {
			throw new ServiceException("本单据未归档，不允许反归档。");
		}
		SysAccountPeriod currPeriod = periodMapper.getCurrentPeriod();
		if(!currPeriod.getFyear().equals(arecBill.getFyear()) ||
				!currPeriod.getPeriod().equals(arecBill.getPeriod())) {
			throw new ServiceException("不是当期单据，不允许反归档。");
		}
		if(contactMapper.isArpBillCheck(billId)) {
			throw new ServiceException("本单据已经核销，不允许反归档。");
		}
		Integer year = arecBill.getFyear();
		Integer period = arecBill.getPeriod();
		Integer custId = arecBill.getCustSuppId();
		Integer deptId = arecBill.getDeptId();
		Integer empId = arecBill.getEmpId();	
		RpContact contact = contactMapper.findRpContactByArpBill(arecBill.getArpBillId());
		if(contact == null) {
			throw new ServiceException("反归档失败，未检索到往来记录。");
		}
		if(contact.getAmount().compareTo(contact.getRemAmount()) != 0) {
			throw new ServiceException("本单据已经核销，不允许反归档。");
		}
		int cnt = contactMapper.revokeContactByArpBill(arecBill.getArpBillId());
		if(cnt == 0) {
			throw new ServiceException("删除往来记录失败，请检查单据是否已经核销。");
		}
		RpContactBalance balance = findContactBalance(1, year, period, custId, deptId, empId);
		if(balance == null) {
			throw new ServiceException("反归档失败，未检索到往来余额记录。");
		}
		cbMapper.recordAccountsReceivableForDebit(balance.getId(), arecBill.getAmount().negate());
		arpBillMapper.billArchive(arecBill.getArpBillId(), false);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.RpArpBillService#unArchiveAPayBill(java.lang.Long)
	 */
	public void unArchiveAPayBill(Long billId) throws ServiceException {
		RpAPayBill apayBill = arpBillMapper.getArpBill(billId);
		if(!apayBill.getArchived()) {
			throw new ServiceException("本单据未归档，不允许反归档。");
		}
		SysAccountPeriod currPeriod = periodMapper.getCurrentPeriod();
		if(!currPeriod.getFyear().equals(apayBill.getFyear()) ||
				!currPeriod.getPeriod().equals(apayBill.getPeriod())) {
			throw new ServiceException("不是当期单据，不允许反归档。");
		}
		if(contactMapper.isArpBillCheck(billId)) {
			throw new ServiceException("本单据已经核销，不允许反归档。");
		}
		Integer year = apayBill.getFyear();
		Integer period = apayBill.getPeriod();
		Integer custId = apayBill.getCustSuppId();
		Integer deptId = apayBill.getDeptId();
		Integer empId = apayBill.getEmpId();
		RpContact contact = contactMapper.findRpContactByArpBill(billId);
		if(contact == null) {
			throw new ServiceException("反归档失败，未检索到往来记录。");
		}
		if(contact.getAmount().compareTo(contact.getRemAmount()) != 0) {
			throw new ServiceException("本单据已经核销，不允许反归档。");
		}
		int cnt = contactMapper.revokeContactByArpBill(billId);
		if(cnt == 0) {
			throw new ServiceException("删除往来记录失败，请检查单据是否已经核销。");
		}		
		RpContactBalance balance = findContactBalance(-1, year, period, custId, deptId, empId);
		if(balance == null) {
			throw new ServiceException("反归档失败，未检索到往来余额记录。");
		}
		cbMapper.recordAccountsPayableForCredit(balance.getId(), apayBill.getAmount().negate());
		arpBillMapper.billArchive(billId, false);
	}
	
	/**
	 * 查找往来余额表
	 * @param direct
	 * @param fyear
	 * @param period
	 * @param custId
	 * @param deptId
	 * @param empId
	 * @return
	 * @throws ServiceException
	 */
	protected RpContactBalance findContactBalance(Integer direct,Integer fyear,Integer period,
			Integer custId,Integer deptId,Integer empId) throws ServiceException {
		if(Configuration.ARP_CHECK_OBJECT_CUST.equals(configuration.getArpCheckObject())) {
			if(custId == null || custId.intValue() == 0) {
				throw new ServiceException("检索往来余额时客户参数为空。");
			}
			return cbMapper.findContactBalanceByCust(direct, fyear, period, custId);
		} else if(Configuration.ARP_CHECK_OBJECT_DEPT.equals(configuration.getArpCheckObject())) {
			if(custId == null || custId.intValue() == 0) {
				throw new ServiceException("检索往来余额时客户参数为空。");
			}
			if(deptId == null || deptId.intValue() == 0) {
				throw new ServiceException("检索往来余额时部门参数为空。");
			}
			return cbMapper.findContactBalanceByDept(direct, fyear, period, custId, deptId);
		} else if(Configuration.ARP_CHECK_OBJECT_EMP.equals(configuration.getArpCheckObject())) {
			if(custId == null || custId.intValue() == 0) {
				throw new ServiceException("检索往来余额时客户参数为空。");
			}
			if(deptId == null || deptId.intValue() == 0) {
				throw new ServiceException("检索往来余额时部门参数为空。");
			}
			if(empId == null || empId.intValue() == 0) {
				throw new ServiceException("检索往来余额时职员参数为空。");
			}
			return cbMapper.findContactBalanceByEmp(direct, fyear, period, custId, deptId, empId);
		} else {
			throw new ServiceException("无效的核算项目类型:" + configuration.getArpCheckObject());
		}
	}
	
	protected RpContactBalance initContactBalance(Integer direct,Integer fyear,Integer period,
			Integer custId,Integer deptId,Integer empId) throws ServiceException {
		
		RpContactBalance balance = null;
		if(Configuration.ARP_CHECK_OBJECT_CUST.equals(configuration.getArpCheckObject())) {
			if(custId == null || custId.intValue() == 0) {
				throw new ServiceException("检索往来余额时客户参数为空。");
			}
			Dept logonDept = this.getCurrentUser().getLogonDept();
			if(logonDept == null) {
				throw new ServiceException("您当前没有登录的部门，操作被拒绝。");
			}
			cbMapper.initContactBalanceByCust(direct, fyear, period, custId,logonDept.getDeptId(), BigDecimal.ZERO);
			balance = cbMapper.findContactBalanceByCust(direct, fyear, period, custId);
		} else if(Configuration.ARP_CHECK_OBJECT_DEPT.equals(configuration.getArpCheckObject())) {
			if(custId == null || custId.intValue() == 0) {
				throw new ServiceException("检索往来余额时客户参数为空。");
			}
			if(deptId == null || deptId.intValue() == 0) {
				throw new ServiceException("检索往来余额时部门参数为空。");
			}
			cbMapper.initContactBalanceByDept(direct, fyear, period, custId, deptId, BigDecimal.ZERO);
			balance = cbMapper.findContactBalanceByDept(direct, fyear, period, custId, deptId);
		} else if(Configuration.ARP_CHECK_OBJECT_EMP.equals(configuration.getArpCheckObject())) {
			if(custId == null || custId.intValue() == 0) {
				throw new ServiceException("检索往来余额时客户参数为空。");
			}
			if(deptId == null || deptId.intValue() == 0) {
				throw new ServiceException("检索往来余额时部门参数为空。");
			}
			if(empId == null || empId.intValue() == 0) {
				throw new ServiceException("检索往来余额时职员参数为空。");
			}
			cbMapper.initContactBalanceByEmp(direct, fyear, period, custId, deptId, empId, BigDecimal.ZERO);
			balance = cbMapper.findContactBalanceByEmp(direct, fyear, period, custId, deptId, empId);
		} else {
			throw new ServiceException("无效的核算项目类型:" + configuration.getArpCheckObject());
		}	
		
		if(balance == null) {
			throw new ServiceException("初始化往来余额失败。");
		}
		return balance;
	}
	/**
	 * 检查单据主体金额与明细金额合计是否一致
	 * @param bill
	 * @return
	 */
	private boolean checkBillAmount(RpBill bill ) {
		BigDecimal amount = bill.getAmount();
		BigDecimal discount = bill.getDiscount();
		//退款单金额不能大于零
		if(Math.abs(bill.getRpBillType().intValue()) == 3 &&
				BigDecimal.ZERO.compareTo(amount) < 0) {
			return false;
		}
		if(bill.getDetails() == null || bill.getDetails().size() == 0) {
			return true;
		}
		BigDecimal detailAmount = BigDecimal.ZERO;
		BigDecimal detailDiscount = BigDecimal.ZERO;
		for(RpBillDetail detail : bill.getDetails()) {
			detailAmount = detailAmount.add(detail.getSettleAmount());
			detailDiscount = detailDiscount.add(detail.getDiscount());
		}
		if(amount.compareTo(detailAmount) == 0 &&
				discount.compareTo(detailDiscount) == 0) {
			return true;
		} else {
			return false;
		}
	}

	public boolean isArpBillCheck(Long billId) {
		return contactMapper.isArpBillCheck(billId);
	}

	public boolean isRpBillCheck(Long billId) {
		return contactMapper.isRpBillCheck(billId);
	}

	public String newNumber(@SuppressWarnings("rawtypes") Class clazz) throws ServiceException {
		int roleId = 0;
		if(RpAPayBill.class.equals(clazz)) {
			roleId = numberRoleConfig.getRpAPayBillRoleId();
		} else if(RpARecBill.class.equals(clazz)) {
			roleId = numberRoleConfig.getRpARecBillRoleId();
		} else if(RpOtherAPayBill.class.equals(clazz)) {
			roleId = numberRoleConfig.getRpOtherAPayBillRoleId();
		} else if(RpOtherARecBill.class.equals(clazz)) {
			roleId = numberRoleConfig.getRpOtherARecBillRoleId();
		} else if(RpRecBill.class.equals(clazz)) {
			roleId = numberRoleConfig.getRpRecBillRoleId();
		} else if(RpPayBill.class.equals(clazz)) {
			roleId = numberRoleConfig.getRpPayBillRoleId();
		} else {
			throw new ServiceException("无效的应收应付单据类型:" + clazz.getName());
		}
		return numberRoleService.newNumber(roleId);
	}

}
